package com.health.admin;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.health.admin.param.LockAdmin;
import com.health.report.ReportForm;
import com.health.result.CodeStatus;
import com.health.result.ResultUtils;
import com.health.result.ResultVo;
import com.health.security.*;
import com.health.security.Admin;
import com.health.security.AdminService;
import com.health.security.Student;
import com.health.security.StudentService;
import com.health.system.model.DataStatsTask;
import com.health.system.model.param.RegionStatsParam;
import com.health.system.model.param.TemperStatsParam;
import com.health.system.model.constant.DataStatsTaskQueueConstants;
import com.health.util.MybatisSQLUtil;
import com.health.vo.ParmVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * 管理员控制器
 * @author: zipeng Li
 * 2021/6/13  15:50
 */
@Slf4j
@RestController
@RequestMapping("/api/admin")
public class AdminController {
    @Resource
    private DefaultKaptcha defaultKaptcha;
    @Resource
    private AdminService adminService;
    @Resource
    private StudentService studentService;
    @Resource
    private ReportFormService reportFormService;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping("/stats/temperature")
    public ResultVo getStatsTemperature(@RequestParam("temperature")float temperature,
                                        @RequestParam("time")String time)  {
        SqlSessionFactory sqlSessionFactory = null;
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("stats-mybatis.xml"));
        } catch (IOException e) {
            e.printStackTrace();
            return ResultUtils.error("Server error");
        }
        TemperStatsParam sParam = new TemperStatsParam();
        sParam.setTemperature(temperature);
        sParam.setTime(time);
        String sql = MybatisSQLUtil.getMyBatisSql("StatsMapper.getTemperStats", sParam, sqlSessionFactory);
        DataStatsTask dataStatsTask = new DataStatsTask(UUID.randomUUID().toString()+".xls",
                sql,60000);
        sendDataStatsTask(dataStatsTask);
        return ResultUtils.success(dataStatsTask.getTaskId());
    }

    @GetMapping("/stats/region")
    public ResultVo getStatsTemperature(@RequestParam("country")String country,
                                        @RequestParam(value = "province",required = false)String province,
                                        @RequestParam(value = "district",required = false)String district)  {
        SqlSessionFactory sqlSessionFactory = null;
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("stats-mybatis.xml"));
        } catch (IOException e) {
            e.printStackTrace();
            return ResultUtils.error("Server error");
        }
        RegionStatsParam sParam = new RegionStatsParam();
        sParam.setCountry(country);
        sParam.setProvince(province);
        sParam.setDistrict(district);
        String sql = MybatisSQLUtil.getMyBatisSql("StatsMapper.getRegionStats", sParam, sqlSessionFactory);
        DataStatsTask dataStatsTask = new DataStatsTask(UUID.randomUUID().toString()+".xls",
                sql,60000);
        sendDataStatsTask(dataStatsTask);
        return ResultUtils.success(dataStatsTask.getTaskId());
    }

    @GetMapping("/stats/task")
    public ResultVo getStatsFileId(@RequestParam("id")String id){
        String url = String.valueOf(redisTemplate.opsForHash().get("export_task",id));
        log.info(url);
        if(url.equals("null"))
            return ResultUtils.error("任务不存在");
        else if(url.equals("process"))
            return ResultUtils.error("任务导出中");
        else
            return ResultUtils.success("导出成功，请在10分钟内下载",url);
    }

    /**
     * 后台登录，获取图形验证码
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("image")
    public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //设置页面缓存方式   不缓存，不存储
        response.setHeader("Cache-Control","no-store, no-cache");
        //设置以图片的形式响应
        response.setContentType("image/jpeg");
        //1.获取验证码字符
        String text = defaultKaptcha.createText();
        log.info("获取验证码：" + text);
        //2.存储到session中
        request.getSession().setAttribute("code",text);
        //3.生成验证码图片
        BufferedImage image = defaultKaptcha.createImage(text);
        //4.输出给前端
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image,"jpg",out);
        if(out != null){
            out.close();
        }
    }

    /**
     * 添加管理员
     * @param admin
     * @return
     */
    @PostMapping("add-admin")
    public ResultVo addAdmin(@RequestBody Admin admin){
        // 检查权限
        Admin principal =(Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(! "1".equals(principal.getIsAdmin())){
            return ResultUtils.error("无此操作权限");
        }
        //查询用户是否存在
        Admin one = adminService.getAdminByUserName(admin.getUsername());
        if(one != null){
            return ResultUtils.error("用户名已经存在!");
        }
        //加密用户密码
        String pwd = passwordEncoder.encode(admin.getPassword());
        admin.setPassword(pwd);
        boolean b = adminService.save(admin);
        if(b){
            return ResultUtils.success("新增管理员成功");
        }else{
            return ResultUtils.error("新增管理员失败");
        }
    }

    /**
     * 管理员锁定
     * @param lockAdmin
     * @return
     */
    @PostMapping("lock-admin")
    public ResultVo LockAdmin(@RequestBody LockAdmin lockAdmin){
        // 检查权限
        Admin principal =(Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(! "1".equals(principal.getIsAdmin())){
            return ResultUtils.error("无此操作权限", CodeStatus.NO_AUTH);
        }
        // 检查是否存在该用户
        Admin admin = adminService.getById(lockAdmin.getId());
        if (admin == null) {
            return ResultUtils.error("不存在该用户", CodeStatus.ERROR_CODE);
        }
        // 锁定用户
        admin.setAccountNonLocked(lockAdmin.isLock());
        adminService.saveOrUpdate(admin);
        return ResultUtils.success(lockAdmin.isLock()?"解锁成功":"锁定成功");
    }

    /**
     * 管理员列表
     * @param parm
     * @return
     */
    @PostMapping("list")
    public ResultVo getList(@RequestBody ParmVo parm){
        IPage<Admin> page = new Page<>();
        page.setCurrent(parm.getStartIndex());
        page.setSize(parm.getPageSize());

        IPage<Admin> adminIPage = adminService.page(page);
        return ResultUtils.success("查询成功", adminIPage);
    }

    /**
     * 用户列表
     * @param parm
     * @return
     */
    @PostMapping("student-list")
    public ResultVo getStudentList(@RequestBody ParmVo parm){
        IPage<Student> page = new Page<>();
        page.setCurrent(parm.getStartIndex());
        page.setSize(parm.getPageSize());

        IPage<Student> adminIPage = studentService.page(page);
        return ResultUtils.success("查询成功", adminIPage);
    }

    void sendDataStatsTask(DataStatsTask dataStatsTask) {
        rabbitTemplate.convertAndSend(DataStatsTaskQueueConstants.STATS_TASK_EXCHANGE_NAME,
                DataStatsTaskQueueConstants.STATS_TASK_ROUTING_KEY_NAME, dataStatsTask, a -> {
                    a.getMessageProperties().setCorrelationId(dataStatsTask.getTaskId());
                    return a;
                });
    }
    /**
     * 获取填报列表
     * @param parmVo
     * @return
     */
    @PostMapping("report-list")
    public ResultVo reportList(@RequestBody ParmVo parmVo){

        IPage<ReportForm> page = new Page<>();
        page.setCurrent(parmVo.getStartIndex());
        page.setSize(parmVo.getPageSize());

        IPage<ReportForm> adminIPage = reportFormService.page(page);
        return ResultUtils.success("查询成功", adminIPage);
    }

    /**
     * 获取表单详情
     * @param id
     * @return
     */
    @GetMapping("report-detail")
    public ResultVo reportDetail(@RequestParam Long id){
        ReportForm reportForm = reportFormService.getById(id);
        Student student = studentService.getById(reportForm.getCentralAuthenticationId());

        HashMap<String, Object> map = new HashMap<>();
        map.put("reportForm", reportForm);
        map.put("student", student);

        return ResultUtils.success("查询成功", map);
    }

    /**
     * 获取统计数据
     * @return
     */
    @GetMapping("statistical-data")
    public ResultVo reportDetail(){
        // 获取用户人数
        Integer studentNumber = studentService.list().size();
        // 获取管理员人数
        Integer adminNumber = adminService.list().size();
        // 获取今日填报人数
        Integer dayRecord = reportFormService.getDayRecords();
        // 获取风险人数
        Integer dangerNumber = reportFormService.getDangerNumber();

        HashMap<Object, Object> map = new HashMap<>(4);
        map.put("studentNumber", studentNumber);
        map.put("adminNumber", adminNumber);
        map.put("dayRecord", dayRecord);
        map.put("dangerNumber", dangerNumber);

        return ResultUtils.success("获取统计信息", map);

    }
}
